package lab.anoper.juc.condition;

import java.util.Random;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @author 闫家洪（yanjiahong@vcredit.com）
 * @since 2024/12/12
 */
public class ParkingLot {
    private static final int MAX_SPACES = 10;
    private static final Random random = new Random();

    private final ReentrantLock lock = new ReentrantLock(true);
    private final Condition fullCond = lock.newCondition();

    private int availSpaces = MAX_SPACES;

    public void park() throws Exception {
        lock.lock();
        try {
            if (availSpaces == 0) {
                System.out.printf("%s，剩余0个车位，等待有空余停车位...\n", Thread.currentThread().getName());
                fullCond.await();
            }
            availSpaces--;
            System.out.printf("%s，剩余%d个车位，已经停入\n", Thread.currentThread().getName(), availSpaces);
        } finally {
            lock.unlock();
        }
    }

    public void unpark() {
        lock.lock();
        try {
            availSpaces++;
            System.out.printf("%s，已经开出，剩余%d个停车位，其他车辆可以停入\r\n", Thread.currentThread().getName(), availSpaces);
            fullCond.signal();
        } finally {
            lock.unlock();
        }
    }

    public static void main(String[] args) {
        final ParkingLot parkingLot = new ParkingLot();
        for (int i = 0; i < 20; i++) {
            Runnable car = () -> {
                randomSleep(2000);
                try {
                    parkingLot.park();
                    randomSleep(10000);
                    parkingLot.unpark();
                } catch (Exception e) {
                    System.out.printf("%s 停车出现异常，" + e.getMessage(), Thread.currentThread().getName());
                }
            };
            new Thread(car).start();
        }
    }

    private static void randomSleep(int maxMills) {
        try {
            int mills = random.nextInt(maxMills);
            Thread.sleep(mills);
        } catch (Exception e) {
            // do nothing
        }
    }

}




















